package com.evl.core.weixin;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import javax.annotation.PostConstruct;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

@Configuration
public class WeixinHandler {

    private static Logger logger = LoggerFactory.getLogger(WeixinHandler.class);

    @Value("${weixin.appID}")
    private String appID;

    @Value("${weixin.appsecret}")
    private String appsecret;

    @Value("${weixin.basic.accesstoken.url}")
    private String basicAccesstokenUrl;
    private String jsapiTimestamp;
    @Value("${weixin.jsapi.noncestr}")
    private String jsapiNoncestr;
    @Value("${weixin.jsapi.ticket.url}")
    private String jsapiTicketUrl;

    @Value("${weixin.template.url}")
    private String templateUrl;
    
	/**
     * WeixinJS
     */
    private String basicAccessToken;
    private String jsapiTicket;
    private Map<String, String> signatureCache = new HashMap<String, String>();

    public String getTemplateUrl() {
		return templateUrl;
	}

	public void setTemplateUrl(String templateUrl) {
		this.templateUrl = templateUrl;
	}

	public String getAppID() {
        return appID;
    }

    public void setAppID(String appID) {
        this.appID = appID;
    }

    public String getAppsecret() {
        return appsecret;
    }

    public void setAppsecret(String appsecret) {
        this.appsecret = appsecret;
    }

    public String getBasicAccesstokenUrl() {
        return basicAccesstokenUrl;
    }

    public void setBasicAccesstokenUrl(String basicAccesstokenUrl) {
        this.basicAccesstokenUrl = basicAccesstokenUrl;
    }

    public String getJsapiTicketUrl() {
        return jsapiTicketUrl;
    }

    public void setJsapiTicketUrl(String jsapiTicketUrl) {
        this.jsapiTicketUrl = jsapiTicketUrl;
    }

    public String getJsapiNoncestr() {
        return jsapiNoncestr;
    }

    public void setJsapiNoncestr(String jsapiNoncestr) {
        this.jsapiNoncestr = jsapiNoncestr;
    }

    public String getJsapiTimestamp() {
        return jsapiTimestamp;
    }

    public void setJsapiTimestamp(String jsapiTimestamp) {
        this.jsapiTimestamp = jsapiTimestamp;
    }

    public String getBasicAccessToken() {
        return basicAccessToken;
    }

    public void setBasicAccessToken(String basicAccessToken) {
        this.basicAccessToken = basicAccessToken;
    }

    public String getJsapiTicket() {
        return jsapiTicket;
    }

    public void setJsapiTicket(String jsapiTicket) {
        this.jsapiTicket = jsapiTicket;
    }

    /**
     * 应用初始化启动定时任务，定时更新token
     */
    @PostConstruct
    private void init() {
        new Timer().schedule(new TimerTask() {
            public void run() {
                jsapiTimestamp = Long.toString(System.currentTimeMillis() / 1000);
                basicAccessToken = requestBasicAccessToken();
                if (basicAccessToken == null) {
                    basicAccessToken = requestBasicAccessToken();
                }
                jsapiTicket = requestJsapiTicket(basicAccessToken);
                if (jsapiTicket == null) {
                    jsapiTicket = requestJsapiTicket(basicAccessToken);
                }
                signatureCache.clear();
            }
        }, 1000, 7200*1000);
    }

    /**
     * String 转换json对象
     * @param text
     * @return
     */
    private JSONObject parse(String text) {
        if (StringUtils.isEmpty(text)) {
            return null;
        }
        try {
            return JSON.parseObject(text);
        } catch (Exception e) {
            return null;
        }
    }

    /** 获取token值，有效日期7200s
     * {"access_token":"ACCESS_TOKEN","expires_in":7200}
     */
    private String requestBasicAccessToken() {
        String text = HttpService.doGet(basicAccesstokenUrl);
        JSONObject parse = parse(text);
        if (parse == null) {
            logger.debug("Request for basic access token failed with url: {}", basicAccesstokenUrl);
            return null;
        }
        String accessToken = parse.getString("access_token");
        logger.debug("Request for basic access token successed, result: {}", accessToken);
        return accessToken;
    }

    /**
     * { "errcode":0, "errmsg":"ok", "ticket":
     * "bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA"
     * , "expires_in":7200 }
     */
    private String requestJsapiTicket(String accessToken) {
    	System.out.println(accessToken);
    	System.out.println(jsapiTicketUrl);
        String text = HttpService.doGet(MessageFormat.format(jsapiTicketUrl, accessToken));
        JSONObject parse = parse(text);
        if (parse == null) {
            logger.debug("Request jsapi ticket failed  with url: {}", jsapiTicketUrl);
            return null;
        }
        String ticket = parse.getString("ticket");
        logger.debug("Request jsapi ticket successed, ticket: {}", ticket);
        return ticket;
    }

    /**
     * url授权
     * @param url
     * @return
     */
    public String getSignature(String url) {
        if (signatureCache.containsKey(url)) {
            String str = signatureCache.get(url);
            logger.debug("Get signature for url: {} from cache successed, signature: {}", url, str);
            return str;
        }
        String str = new StringBuilder("jsapi_ticket=").append(jsapiTicket).append("&noncestr=").append(jsapiNoncestr)
                .append("&timestamp=").append(jsapiTimestamp).append("&url=").append(url).toString();
        String signature = DigestUtils.shaHex(str);
        logger.debug("Get signature for url: {} successed, signature: {}", url, signature);
        signatureCache.put(url, signature);
        return signature;
    }

}
